package main;

import java.util.Vector;

import javax.microedition.lcdui.Canvas;
import javax.microedition.lcdui.CommandListener;
import javax.microedition.lcdui.Display;
import javax.microedition.lcdui.Displayable;
import javax.microedition.lcdui.Graphics;
import javax.microedition.lcdui.Image;

import model.Command;
import model.IAction;
import model.Position;
import screen.CameraList;
import screen.ChatTextField;
import screen.Dialog;
import screen.InputDlg;
import screen.LoginScr;
import screen.MainScr;
import screen.Menu;
import screen.MsgDlg;
import screen.QuestCompletedDlg;
import screen.Screen;
import utilities.GameResource;
import animation.Effect;

public class GameCanvas extends Canvas implements CommandListener, Runnable {
    // 0 1 2 3 4 5 6 7 8 9 * LSoft RSoft

    public static boolean[] keyPressed = new boolean[14];
    
    public static boolean[] keyReleased = new boolean[14];
    
    public static boolean[] keyHold = new boolean[14];

    
    public static boolean isMoto, isWifi = false;
    long lastTimePress = 0;
    int vibrateTime;
    public static CameraList cameraList = new CameraList();
    //Black Berry
    public static boolean isBB;
    ///////////////
    public static GameCanvas instance;
    static boolean bRun;
    public boolean isClick = false;
    int count = 1;
    public static boolean isPointerDown;
    public static boolean isPointerClick;
    public static int px, py, pxLast, pyLast;
    public static int gameTick;
    public static int w, h, hw, hh, wd3, hd3, w2d3, h2d3, w3d4, h3d4;
    public static int hBottomBar;
    
    public static Vector listPoint;
    private Image m_imgBuff;
    
    //DECRALCE SCREEN AND DIALOG
    public static InputDlg inputDlg = new InputDlg();
    public static Screen currentScreen;
    public static MsgDlg msgdlg = new MsgDlg();
    public static QuestCompletedDlg questCompletedDlg = new QuestCompletedDlg();
    
    public static MainScr mainScr;
    public static Menu menu = new Menu();
    public static LoginScr loginScr;
    public static Dialog currentDialog;
    public static Vector m_arrEffect = new Vector();
    
    public GameCanvas() {
        this.setFullScreenMode(true);

        instance = this;

        //get screen size
        w = GameCanvas.instance.getWidth();
        h = GameCanvas.instance.getHeight();

        //create image buffer
        m_imgBuff = Image.createImage(w, h);
        
      //  System.gc();

        connect();
    }

    public static void connect() {
        String host = "socket://" + NuoiThuMidlet.IP + ":" + NuoiThuMidlet.PORT;
        if (isWifi) {
            host += ";interface=wifi";
        }
    }

    //process key press event
    public void keyPressed(int keyCode) {
    	// TODO Auto-generated method stub
        lastTimePress = System.currentTimeMillis();

        if (isMoto) {
            switch (getGameAction(keyCode)) {
                case Canvas.UP:
                    keyHold[2] = true;
                    keyPressed[2] = true;
                    return;
                case Canvas.DOWN:
                    keyHold[8] = true;
                    keyPressed[8] = true;
                    return;
                case Canvas.LEFT:
                    keyHold[4] = true;
                    keyPressed[4] = true;
                    return;
                case Canvas.RIGHT:
                    keyHold[6] = true;
                    keyPressed[6] = true;
                    return;
                case Canvas.FIRE:
                    keyHold[5] = true;
                    keyPressed[5] = true;
                    return;
            }
            if (keyCode == -21) // Soft 1
            {
                keyCode = -6;
            } else if (keyCode == -22) // Soft 2
            {
                keyCode = -7;
            }
        } else if (isBB) {// BB:
            switch (keyCode) {
                case Canvas.UP:// keyCode = 1
                    keyHold[2] = true;
                    keyPressed[2] = true;
                    return;
                case Canvas.DOWN:// keyCode = 6
                    keyHold[8] = true;
                    keyPressed[8] = true;
                    return;
                case Canvas.LEFT:// keyCode = 2
                    keyHold[4] = true;
                    keyPressed[4] = true;
                    return;
                case Canvas.RIGHT:// keyCode = 5
                    keyHold[6] = true;
                    keyPressed[6] = true;
                    return;
                case -Canvas.FIRE:// keyCode = 8
                    keyHold[5] = true;
                    keyPressed[5] = true;
                    return;
            }
        }
        mapKeyPress(keyCode);
    }

    //process for key released event
    public void keyReleased(int keyCode) {
        // TODO Auto-generated method stub
        if (isMoto) {
            switch (getGameAction(keyCode)) {
                case Canvas.UP:
                    keyHold[2] = false;
                    return;
                case Canvas.DOWN:
                    keyHold[8] = false;
                    return;
                case Canvas.LEFT:
                    keyHold[4] = false;
                    return;
                case Canvas.RIGHT:
                    keyHold[6] = false;
                    return;
                case Canvas.FIRE:
                    keyHold[5] = false;
                    return;
            }
            if (keyCode == -21) // Soft 1
            {
                keyCode = -6;
            } else if (keyCode == -22) // Soft 2
            {
                keyCode = -7;
            }
        } else if (isBB) {// BB:
            switch (keyCode) {
                case Canvas.UP:
                    keyHold[2] = false;
                    return;
                case Canvas.DOWN:
                    keyHold[8] = false;
                    return;
                case Canvas.LEFT:
                    keyHold[4] = false;
                    return;
                case Canvas.RIGHT:
                    keyHold[6] = false;
                    return;
                case -Canvas.FIRE:
                    keyHold[5] = false;
                    return;
            }
            if (keyCode == 27) // Soft 2
            {
                keyCode = -7;
            }
        }
        mapKeyRelease(keyCode);
    }

    //check for mouse down event in rectangle (x, y, width, height)
    public static boolean isPointer(int x, int y, int w, int h) {
        if (!isPointerDown && !isPointerClick) {
            return false;
        }
        if (px >= x && px <= x + w && py >= y && py <= y + h) {
            return true;
        }
        return false;
    }

    //clear events
    public static void clearKeyPressed() {
        isPointerClick = false;
        for (int i = 0; i < 14; i++) {
            keyPressed[i] = false;
        }
    }

    protected void paint(Graphics gDisplay) {
        // TODO Auto-generated method stub
        Graphics g = m_imgBuff.getGraphics();
        if (currentScreen != null) {
            currentScreen.paint(g);
            g.translate(-g.getTranslateX(), -g.getTranslateY());
            int i;
            for(i = 0; i < m_arrEffect.size(); i++){
            	Effect ef = (Effect)m_arrEffect.elementAt(i);
            	ef.paint(g);
            }
            
        	ChatTextField.gI().paint(g);
            g.setClip(0, 0, GameCanvas.w, GameCanvas.h);
        }

        g.translate(-g.getTranslateX(), -g.getTranslateY());
        g.setClip(0, 0, w, h);

        if (currentDialog != null) {
            currentDialog.paint(g);
        } else if (menu.m_showMenu) {
            menu.paintMenu(g);
        }
        
        g.setColor(0xe8fd02);
        if (isClick) {
            g.fillRect(px - count + (count * 2) / 2, py - count, 1, count * 2 + 1);
            g.fillRect(px - count, py - count + (count * 2) / 2, count * 2 + 1, 1);
            if (gameTick % 2 == 0) {
                count++;
            }
            if (count > 3) {
                isClick = false;
                count = 0;
            }
        }
        if (hasPointerEvents() && listPoint.size() > 0) {
            for (int i = 0; i < listPoint.size(); i++) {
                Position pos = (Position) listPoint.elementAt(i);
                pos.anchor++;
                g.fillRect(pos.x + pos.anchor / 2, pos.y, 1, pos.anchor);
                g.fillRect(pos.x, pos.y + pos.anchor / 2, pos.anchor, 1);
                if (pos.anchor > 2) {
                    listPoint.removeElement(pos);
                    i--;
                }
            }
        }

        gDisplay.drawImage(m_imgBuff, 0, 0, 0);
    }
    
    protected void pointerDragged(int x, int y) {
        // TODO Auto-generated method stub
        listPoint.addElement(new Position(x, y));
        px = x;
        py = y;
    }

    protected void pointerPressed(int x, int y) {
        // TODO Auto-generated method stub
        isClick = true;
        isPointerDown = true;
        pxLast = x;
        pyLast = y;
        px = x;
        py = y;
    }

    protected void pointerReleased(int x, int y) {
        // TODO Auto-generated method stub
        isPointerDown = false;
        isPointerClick = true;
        px = x;
        py = y;

    }

    protected void sizeChanged(int w, int h) {
        // TODO Auto-generated method stub
    }

    //implement CommandListener
    public void commandAction(Command arg0, Displayable arg1) {
        // TODO Auto-generated method stub
    }

    //implement Runnable
    public void run() {
        // TODO Auto-generated method stub
        bRun = true;
        while (bRun) {
            try {
                if (vibrateTime > 0) {
                    vibrateTime--;
                    if (vibrateTime == 0) {
                        Display.getDisplay(NuoiThuMidlet.instance).vibrate(0);
                    }
                }
                long l1 = System.currentTimeMillis();
                gameTick++;
                if (gameTick > 10000) {
                    if (System.currentTimeMillis() - lastTimePress > 300000) {
                        //destroy application if it is not active in a long time ....
                        NuoiThuMidlet.instance.notifyDestroyed();
                    }
                    gameTick = 0;
                }
                
                if (currentScreen != null) {
                    //update current screen
                	ChatTextField.gI().update();
                    currentScreen.update();

                    //update others
                    if (cameraList.isShow) {
                        cameraList.moveCamera();
                    }
                    if (currentDialog != null) {
                        currentDialog.update();
                    } else if (menu.m_showMenu) {
                        menu.updateMenu();
                        menu.updateMenuKey();
                    } else {
                        currentScreen.updateKey();
                        if (cameraList.isShow) {
                            cameraList.updateKey();
                        }
                    }
                    
                    int i;
                    for(i = 0; i < m_arrEffect.size(); i++){
                    	Effect ef = (Effect)m_arrEffect.elementAt(i);
                    	ef.update();
                    }
                }
                isPointerClick = false;
                repaint();
                serviceRepaints();

                // Synchronize time
                long l2 = System.currentTimeMillis() - l1;
                try {
                    if (l2 < 50) {
                        Thread.sleep(50 - l2);
                    } else {
                        Thread.sleep(1);
                    }
                } catch (InterruptedException e) {
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    public void start() {
        new Thread(this).start();
    }

    //stuff
    private void mapKeyRelease(int keyCode) {
        // TODO Auto-generated method stub
        switch (keyCode) {
            case 42:
                keyHold[10] = false;
                keyReleased[10] = true;
                break; // Key [*]
            case 35:
                keyHold[11] = false;
                keyReleased[11] = true;
                break; // Key [#]
            case -6:
            case -21:
                keyHold[12] = false;
                keyReleased[12] = true;
                break; // Soft1
            case -7:
            case -22:
                keyHold[13] = false;
                keyReleased[13] = true;
                break; // Soft2
            case -5:
            case 10:
                keyHold[5] = false;
                keyReleased[5] = true;
                break; // [i]
            case -1:
            case -38:
                keyHold[2] = false;
                break; // UP
            case -2:
            case -39:
                keyHold[8] = false;
                break; // DOWN
            case -3:
                keyHold[4] = false;
                break; // LEFT
            case -4:
                keyHold[6] = false;
                break; // RIGHT
        }
    }

    private void mapKeyPress(int keyCode) {
        // TODO Auto-generated method stub

        if (currentDialog != null) {
            currentDialog.keyPress(keyCode);
        } else if (!GameCanvas.menu.m_showMenu) {
        	if (ChatTextField.gI().isShow)
				ChatTextField.gI().keyPressed(keyCode);
			else
				currentScreen.keyPress(keyCode);
        }


        switch (keyCode) {
            case 42:
                keyHold[10] = true;
                keyPressed[10] = true;
                break; // Key [*]
            case 35:
                keyHold[11] = true;
                keyPressed[11] = true;
                break; // Key [#]
            case -6:
            case -21:
                keyHold[12] = true;
                keyPressed[12] = true;
                break; // Soft1
            case -7:
            case -22:
                keyHold[13] = true;
                keyPressed[13] = true;
                break; // Soft2
            case -5:
            case 10:
                keyHold[5] = true;
                keyPressed[5] = true;
                break; // [i]
            case -1:
            case -38:
                keyHold[2] = true;
                keyPressed[2] = true;
                break; // UP
            case -2:
            case -39:
                keyHold[8] = true;
                keyPressed[8] = true;
                break; // DOWN
            case -3:
                keyHold[4] = true;
                keyPressed[4] = true;
                break; // LEFT
            case -4:
                keyHold[6] = true;
                keyPressed[6] = true;
                break; // RIGHT
        }
    }

    public void initGameCanvas() {
        isMoto = (getKeyCode(Canvas.FIRE) == -20);

        w = GameCanvas.instance.getWidth();
        h = GameCanvas.instance.getHeight();

        hw = w / 2;
        hh = h / 2;
        wd3 = w / 3;
        hd3 = h / 3;
        w2d3 = 2 * w / 3;
        h2d3 = 2 * h / 3;
        w3d4 = 3 * w / 4;
        h3d4 = 3 * h / 4;

        hBottomBar = 20;

        /////////////////INIT SCREEN////////////////
        loginScr = new LoginScr();
        mainScr = MainScr.gI();
        
        listPoint = new Vector();
    }

    public static Position getMinMaxFor(int cmy, int w, int size, int numW, int hLimit) {
        Position p = new Position(0, size);
        if (cmy > 0) {
            p.x = (cmy / w) * numW;
        }
        if (p.y * w > hLimit - w) {
            p.y = p.x + ((hLimit) / w) * numW + numW;
            if (p.y > size) {
                p.y = size;
            }
        }
        return p;
    }
    public static model.Command cmdEndDlg = new model.Command(GameResource.no, new IAction() {

        public void perform() {
            GameCanvas.endDlg();
        }
    });

    //close dialog
    public static void endDlg() {
        msgdlg.isWaiting = false;
        currentDialog = null;
        
    }

    //open ok dialog with the info message
    public static void startOKDlg(String info) {
        endDlg();
        msgdlg.setInfo(info, new model.Command(GameResource.OK, new IAction() {

            public void perform() {
                currentDialog = null;
            }
        }), null);
        currentDialog = msgdlg;
    }
    
    //open dialog with the info message in bottom
    public static void startOKBot(String info, Vector listCmd, byte position) {
        endDlg();
        msgdlg.setInfo(info, new model.Command(GameResource.OK, new IAction() {

            public void perform() {
                currentDialog = null;
            }
        }), listCmd, position);
        currentDialog = msgdlg;
    }

    //open dialog with the info message and list command
    public static void startOKDlg(String info, Vector listCmd) {
        endDlg();
        msgdlg.setInfo(info, new model.Command("", new IAction() {

            public void perform() {
                currentDialog = null;
            }
        }), listCmd);
        currentDialog = msgdlg;
    }

    //open yes no dialog
    public static void startOKDlg(String info, IAction yes) {
        Vector menu = new Vector();
        menu.addElement(new Command(GameResource.yes, yes));
        menu.addElement(cmdEndDlg);
        startOKDlg(info, menu);
    }

    //open ok dialog with custom handler event when user choice ok 
    public static void startOK(String info, IAction ok) {
        Vector menu = new Vector();
        menu.addElement(new Command(GameResource.OK, ok));
        startOKDlg(info, menu);
    }
    
    //in bottom
    public static void startOK(String info, IAction ok, byte position) {
        Vector menu = new Vector();
        menu.addElement(new Command(GameResource.OK, ok));
        startOKBot(info, menu, position);
    }

    //open waiting dialog
    public static void startWaitDlg(String info) {
        endDlg();
        msgdlg.isWaiting = true;
        msgdlg.setInfo(info, null, null);
        currentDialog = msgdlg;
    }

  //open quest completed dialog
    public static void showQuestCompletedDlg(int questLevel, int bonusMoney1, int bonusMoney2, int bonusXp, Vector vtBonusItems, model.Command centerCmd) {
        endDlg();
        questCompletedDlg.setCenterCmd(centerCmd);
        questCompletedDlg.setInfo(questLevel, bonusMoney1, bonusMoney2, bonusXp, vtBonusItems);
        questCompletedDlg.show();
    }
    
	public void commandAction(javax.microedition.lcdui.Command arg0,
			Displayable arg1) {
		// TODO Auto-generated method stub
		
	}
}
